//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using OpenLS.Spreadsheet.Collections;
using OpenLS.Spreadsheet.Expressions;

namespace OpenLS.Spreadsheet
{
	partial class Worksheet
	{
        class WorksheetPanesDisabler : IDisposable
        {
            private List<IDisposable> _paneDisablers;

            public WorksheetPanesDisabler(Worksheet worksheet)
            {
                this._paneDisablers = Enumerable.ToList(Enumerable.Select(worksheet.GetPanes(), p => p.CreateDisabler()));

            }

            public void Dispose()
            {
                foreach (var item in _paneDisablers)
                    item.Dispose();
            }
        }
        internal IDisposable CreateWorksheetPanesDisabler()
        {
            return new WorksheetPanesDisabler(this);
        }
        class TemporaryMovedCells : IDisposable
        {
            public TemporaryMovedCells(Worksheet ws, Predicate<CellAddress> predicate)
            {
                Contract.Requires(ws != null);
                this._disabler = ws.Workbook.CreateCalculationDisabler();
                this._paneDisabler = new WorksheetPanesDisabler(ws);
                _worksheet = ws;
                foreach (Cell cell in ws.NonVolatileCells)
                    if (predicate(cell.Address))
                        _cells.Add(cell);
                foreach (Cell cell in _cells)
                {
                    ws.removeCellWithEvents(cell);
                    //\\Contract.Assert(!ws.TopLeftPane.Cells.Contains(cell));
                }
                ws.Cells.RemoveVolatileCells(predicate);
            }
            private readonly List<Cell> _cells = new List<Cell>();
            internal IEnumerable<Cell> GetCells(){
                return _cells;}
            private readonly List<Cell> _volatileCells = new List<Cell>();
            readonly Worksheet _worksheet;
            private readonly IDisposable _disabler;
            private readonly WorksheetPanesDisabler _paneDisabler;

            #region IDisposable Members

            public void Dispose()
            {
                {
                    foreach (Cell cell in _cells)
                    {
                        _worksheet.addCell(cell, false);
                      //\\  _worksheet.NotifyValueChanged(cell, null); //\\ for charts
                    }
                    foreach (Cell cell in _volatileCells)
                    {
                        _worksheet.Cells.ForceVolatileCell(cell);
                    }
                }
                this._disabler.Dispose();
                _paneDisabler.Dispose();
            }

            #endregion
        }
	    private void fixupSharedFormulas(Worksheet worksheet, Predicate<Cell> cellPredicate, CellRelativeAddress offset)
	    {
            fixupSharedFormulas(
                SharedExpressionHelper.GetSharedFormulas(
                Enumerable.Where(worksheet.NonVolatileCells, cellPredicate)),
cellPredicate, offset);
	    }

	    private void fixupSharedFormulas(IEnumerable<SharedExpression> sharedExpressions, Predicate<Cell> cellPredicate, CellRelativeAddress offset)
	    {
            foreach (SharedExpression sharedExpression in sharedExpressions)
            {
                Range sharedExpressionRange = new MultiCellsRange(this, sharedExpression.Address);
                foreach (Cell cellWithPotentialSharedExpression in sharedExpressionRange.GetNonEmptyCells())
                {
                    var sharedExpressionReference =
                        cellWithPotentialSharedExpression.Expression as SharedExpressionReference;
                    if (sharedExpressionReference == null)
                        continue;
                    bool inMove = cellPredicate(cellWithPotentialSharedExpression);
                    foreach (
                        IDependencyNode node in
                            sharedExpressionReference.GetPrecedents(
                                new CellEvaluationContext(cellWithPotentialSharedExpression)))
                    {
                        var referencedCell = (Cell)node;
                        if (referencedCell == null)
                            continue; //\\do names as well

                        if (cellPredicate(referencedCell) != inMove)
                        {
                            SharedExpressionHelper.Unshare(cellWithPotentialSharedExpression);
                            break;
                        }
                    }
                }
            }
            foreach (SharedExpression sharedExpression in sharedExpressions)
            {
                //\\sharedExpression.Range = sharedExpression.Range + (destination - source.TopLeft.Address);
                sharedExpression.Offset(offset);
            }
	        
	    }

	    internal void OnCellRemoved(Cell cell)
	    {
	        var c = CellsRemoved;
            if (c != null)
                c(this, new CellRegionEventArgs(new SingleCellRegion (cell)));
	    }
        internal event EventHandler<CellRegionEventArgs> CellsRemoved;

	}
}
